<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>speedtest1.wasm</title>
  </head>
  <body>
    <header id='titlebar'><span>speedtest1.wasm</span></header>
    <div>See also: <a href='speedtest1-worker.html'>A Worker-thread variant of this page.</a></div>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>
    </div><!-- /emscripten bits -->
    <div class='warning'>This page starts running the main exe when it loads, which will
      block the UI until it finishes!</div>
    </div>
    <div class='warning'>Achtung: running it with the dev tools open may
      <em>drastically</em> slow it down. For faster results, keep the dev
      tools closed when running it!
    </div>
    <div>Output is delayed/buffered because we cannot update the UI while the
      speedtest is running. Output will appear below when ready...
    <div id='test-output'></div>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="jswasm/speedtest1.js"></script>
    <script>(function(){
    /**
       If this environment contains WASMFS with OPFS, this function
       initializes it and returns the name of the dir on which OPFS is
       mounted, else it returns an empty string.
    */
    const wasmfsDir = function f(wasmUtil){
      if(undefined !== f._) return f._;
      const pdir = '/persistent';
      if( !self.FileSystemHandle
          || !self.FileSystemDirectoryHandle
          || !self.FileSystemFileHandle){
        return f._ = "";
      }
      try{
        if(0===wasmUtil.xCallWrapped(
          'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
        )){
          return f._ = pdir;
        }else{
          return f._ = "";
        }
      }catch(e){
        // sqlite3_wasm_init_wasmfs() is not available
        return f._ = "";
      }
    };
    wasmfsDir._ = undefined;

    const eOut = document.querySelector('#test-output');
    const log2 = function(cssClass,...args){
      const ln = document.createElement('div');
      if(cssClass) ln.classList.add(cssClass);
      ln.append(document.createTextNode(args.join(' ')));
      eOut.append(ln);
      //this.e.output.lastElementChild.scrollIntoViewIfNeeded();
    };
    const logList = [];
    const dumpLogList = function(){
      logList.forEach((v)=>log2('',v));
      logList.length = 0;
    };
    /* we cannot update DOM while speedtest is running unless we run
       speedtest in a worker thread. */;
    const log = (...args)=>{
      console.log(...args);
      logList.push(args.join(' '));
    };
    const logErr = function(...args){
      console.error(...args);
      logList.push('ERROR: '+args.join(' '));
    };

    const runTests = function(sqlite3){
      globalThis.S = sqlite3;
      const capi = sqlite3.capi, wasm = sqlite3.wasm;
      //console.debug('sqlite3 (global S) =',sqlite3);
      const pDir = wasmfsDir(wasm);
      if(pDir){
        console.warn("wasmfs storage:",pDir);
      }
      const scope = wasm.scopedAllocPush();
      let dbFile = pDir+"/speedtest1.db";
      const urlParams = new URL(self.location.href).searchParams;
      const argv = ["speedtest1"];
      if(urlParams.has('flags')){
        argv.push(...(urlParams.get('flags').split(',')));
      }

      let forceSize = 0;
      let vfs, pVfs = 0;
      if(urlParams.has('vfs')){
        vfs = urlParams.get('vfs');
        pVfs = capi.sqlite3_vfs_find(vfs);
        if(!pVfs){
          log2('error',"Unknown VFS:",vfs);
          return;
        }
        argv.push("--vfs", vfs);
        log2('',"Using VFS:",vfs);
        if('kvvfs' === vfs){
          //forceSize = 10
          /* --size > 2 is too big for local/session storage
             as of mid-2025, but kvvfs v2 (late 2025)
             lets us use transient storage. */;
          dbFile = 'transient';
          log2('warning',"kvvfs VFS: forcing --size",forceSize,
               "and filename '"+dbFile+"'.");
          capi.sqlite3_js_kvvfs_clear(dbFile);
        }
      }
      if(forceSize){
        argv.push('--size',forceSize);
      }else{
        [
          'size'
        ].forEach(function(k){
          const v = urlParams.get(k);
          if(v) argv.push('--'+k, urlParams[k]);
        });
      }
      argv.push(
        "--singlethread",
        //"--nomutex",
        //"--nosync",
        //"--memdb", // note that memdb trumps the filename arg
        "--nomemstat"
      );
      argv.push("--big-transactions"/*important for tests 410 and 510!*/,
                dbFile);
      console.log("argv =",argv);
      // These log messages are not emitted to the UI until after main() returns. Fixing that
      // requires moving the main() call and related cleanup into a timeout handler.
      if(pDir) wasm.sqlite3_wasm_vfs_unlink(pVfs,dbFile);
      log2('',"WASM heap size:",sqlite3.wasm.heap8().byteLength,"bytes");
      log2('',"WASM pointer size:",sqlite3.wasm.ptr.size);
      log2('',"Starting native app:\n ",argv.join(' '));
      log2('',"This will take a while and the browser might warn about the runaway JS.",
           "Give it time...");
      logList.length = 0;
      setTimeout(function(){
        wasm.xCall('wasm_main', argv.length,
                   wasm.scopedAllocMainArgv(argv));
        wasm.scopedAllocPop(scope);
        if('kvvfs'===vfs){
          logList.unshift("KVVFS "+dbFile+" size = "+
                          capi.sqlite3_js_kvvfs_size(dbFile));
        }
        if(pDir) wasm.sqlite3_wasm_vfs_unlink(pVfs,dbFile);
        logList.unshift("Done running native main(). Output:");
        dumpLogList();
        log2('',"WASM heap size:",sqlite3.wasm.heap8().byteLength,"bytes");
      }, 50);
    }/*runTests()*/;

    self.sqlite3TestModule.print = log;
    self.sqlite3TestModule.printErr = logErr;
    sqlite3InitModule.__isUnderTest = true;
    sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();</script>
</body>
</html>
